package com.dcloud.core.client;

import com.dcloud.core.enums.ErrorCode;
import com.dcloud.core.exception.DtLoaderException;
import com.dcloud.core.overall.OverallVariable;
import com.dcloud.core.source.ISource;
import com.dcloud.core.source.RdbmsSource;
import com.dcloud.core.source.impl.InfluxDbSource;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.Pong;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Component("INFLUXDB")
@Slf4j
public class InfluxClient implements IClient<InfluxDbMapList> {
    static OkHttpClient.Builder client = new OkHttpClient.Builder()
            .readTimeout(100, TimeUnit.SECONDS);

    /**
     * @Description influxdb 不支持获取连接
     * @Author shijf
     * @Date 17:06 2022/8/31
     */
    @Override
    public Connection getCon(ISource source) {
        throw new DtLoaderException(ErrorCode.NOT_SUPPORT.getDesc());
    }

    @Override
    public Connection getCon(ISource source, String taskParams) {
        throw new DtLoaderException(ErrorCode.NOT_SUPPORT.getDesc());
    }

    /**
     * @Description //influxdb 测试连接
     * @param source
     * @return java.lang.Boolean
     * @Author shijf
     * @Date 17:11 2022/8/31
     */
    @Override
    public Boolean testCon(ISource source) {

        try {
            InfluxDbSource influxDbSource = (InfluxDbSource) source;
            InfluxDB influxDB = InfluxDBFactory.connect(influxDbSource.getUrl()
                    , influxDbSource.getUsername()
                    , influxDbSource.getPassword()
                    , client);
            influxDB.setDatabase(influxDbSource.getSchema());
            Pong pong = influxDB.ping();
            if (pong != null) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * @Description 获取influxDb
     * @param iSource
     * @return InfluxDB
     * @Author shijf
     * @Date 14:49 2022/8/8
     */
    private InfluxDB getInfluxDB(InfluxDbSource iSource) {

        InfluxDbSource defineSource = iSource;
        //查询全局静态变量中是否存在
        Object vByCode = OverallVariable.getVByCode(defineSource.getUrl());
        InfluxDB influxDB = null;
        if(vByCode == null){
            influxDB = InfluxDBFactory.connect(defineSource.getUrl()
                    , defineSource.getUsername()
                    , defineSource.getPassword()
                    , client);

            influxDB.setDatabase(defineSource.getSchema());
            OverallVariable.setVByCode(defineSource.getUrl(),influxDB);
        }else{
            influxDB = (InfluxDB)vByCode;
        }

        return influxDB;
    }

    /**
     * 操作数据库
     *
     * @return
     */
    public QueryResult query(InfluxDB influxDB,String command) {
        try {
            return influxDB.query(new Query(command));
        } catch (Exception e) {
            log.error("influx select failed,{}",e.getMessage());
            throw new DtLoaderException(String.format("influx SQL execute exception：%s", e.getMessage()), e);
        }
    }

    @Override
    public List<InfluxDbMapList> execQuery(ISource defineSource, String taskSql) {
        InfluxDB influxDB = getInfluxDB((InfluxDbSource) defineSource);
        QueryResult influxDBResult = this.query(influxDB, taskSql);
        //解析influxDB数据
        //解析opc数据 放入TSDB的LastDataValue对象
        List<QueryResult.Result> influxResults = influxDBResult.getResults();
        List<InfluxDbMapList> list = new LinkedList<>();
        influxResults.stream().forEach(entity -> {
            //series就每一个influxql 查询的结果返回
            if (entity.getSeries() != null) {

                entity.getSeries().stream().forEach(series -> {
                    //获取value
                    List<List<Object>> valueList = series.getValues();
                    //获取tags
                    Map<String, String> tags = series.getTags();
                    //获取measurements
                    String measurements = series.getName();

                    InfluxDbMapList result = new InfluxDbMapList();
                    result.setMetric(measurements);

                    LinkedHashMap<Long,Object> valueMap = new LinkedHashMap<>();

                    List<InfluxDBObject> objList = new LinkedList<>();


                    for (List<Object> value : valueList) {
                        InfluxDBObject obj = new InfluxDBObject();
                        // 第一个字段是influxdb的时间戳，查询时间戳
                        String field1 = value.get(0) == null ? null : value.get(0).toString();
                        obj.setTime(UTCTimeTran(field1));
                        // 第二个字段是influxdb的field,查询value
                        String field2 = value.get(1) == null ? null : value.get(1).toString();
                        obj.setValue(field2);
                        obj.setCompareValue(Double.valueOf(field2));
                        //第三字段是tag
                        String field3 = value.get(2) == null ? null : value.get(2).toString();
                        result.setTag(field3);
                        obj.setTag(field3);
                        obj.setMetric(measurements);
                        objList.add(obj);
                    }

                    result.setValues(objList);

                    list.add(result);

                });
            }
        });

        return list;
    }

    @Override
    public Long execQueryCount(ISource defineSource, String taskSql) {
        return null;
    }

    @Override
    public List<Map<String, Object>> execQueryWithLimit(ISource defineSource, String taskSql, Long offset, Long rows) {
        return null;
    }

    @Override
    public List getAllTable(RdbmsSource defineSource) {
        return null;
    }

    @Override
    public Boolean createTable(ISource defineSource, String createTableSql) {
        return null;
    }

    //将UTC时间转化成标准格式
    public static Date UTCTimeTran(String dateTime) {
        if(dateTime.contains("Z")) {
            if(dateTime.contains(".")){
                dateTime = dateTime.substring(0, dateTime.indexOf("."));
                dateTime = dateTime + " UTC";
            }
            else{
                dateTime = dateTime.replace("Z"," UTC");
            }

            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z");
            SimpleDateFormat defaultFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date time = format.parse(dateTime);
                return time;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }
}
